iT邦幫忙

2023 iThome 鐵人賽

DAY 12
0

寫可維護的程式 章節中,第五點原則提到了「讓程式碼可複用和可泛化」。今天,我們將著手開發功能,即將原有的 HTML 切版與 JavaScript 邏輯結合。具體來說,我們將創建一個名為 Lightbox.vue 的元件。

https://ithelp.ithome.com.tw/upload/images/20230927/20107703elQ8bscahW.png

Lightbox 元件結構

Lightbox 元件主要包含兩部分:

  1. 可觸發的圖標(icon)
  2. 燈箱內容畫面
    由於我們使用 Vue.js,我們將利用 Vue 的 slot 和 teleport 標籤來實現這一功能。具體來說,slot 標籤的 name 屬性可以用來定位觸發圖標和燈箱內容。

Lightbox.vue 基本結構

<template>
  <div
    class="h-5 border-2 border-[#b1aea4] text-[#b1aea4] rounded-full"
    @click="handleShowInstructions"
  >
    <slot name="lightbox-trigger" />
  </div>
  <Teleport to="body">
    <div
      v-if="isShowInstructions"
      class="mx-auto w-11/12 px-4 py-12 absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white rounded-lg z-20"
    >
      <i-iconoir-cancel
        class="absolute right-2 top-2 text-xl"
        @click="handleShowInstructions"
      />
      <slot name="lightbox-content" />
    </div>
  </Teleport>
</template>
<script setup>
    import { ref } from 'vue';
    const isShowInstructions = ref(false);
    const handleShowInstructions = () => {
      isShowInstructions.value = !isShowInstructions.value;
    };
</script>

Lightbox.vue 父組件

<template #lightbox-trigger>
    <i-healthicons-question-mark
      class="text-sm"
    />
</template>
<template #lightbox-content>
  <!-- 略,與原文相同 -->
</template>

功能說明

這裡,isShowInstructions 用於控制燈箱是否顯示,而 handleShowInstructions 用於切換這一狀態。當使用者點擊 icon 圖標時,燈箱會打開並顯示相應內容。這是一個非常基本的實作,但開源工具如 vue-easy-lightbox 提供了更多高級功能,例如圖像預加載、縮放和滑動等。

註:如直接使用開源工具,則要考慮其相容性與維護性。

Lightbox 優化

為了提高組件的靈活性,我們可以進一步優化它。具體來說,我們可以使用 props 或自定義事件來控制 isShowInstructions,這樣父組件就能更靈活地控制這個元件。

Lightbox.vue 優化

const props = defineProps({
    isShow: {
        type: Boolean,
        default: false,
        required: true
    },
});

const emit = defineEmits(['update:isShow']);

const toggleInstructions = () => {
  emit('update:isShow', !props.isShow);
}; 

Lightbox.vue 父組件優化調整

<Lightbox
      :is-show="isShowInstructions"
      @update:is-show="handleShowInstructions"
>
    <!-- 略,與原文相同 -->
</Lightbox>
import Lightbox from './Lightbox.vue';
import { ref } from 'vue';

const isShowInstructions = ref(false);
const handleShowInstructions = (ev) => {
  isShowInstructions.value = ev;
};

注意事項

我們使用 ChatGPT 協助開法,而 ChatGPT 提供的程式碼可能不完全正確,因此在使用前應進行驗證。例如,在優化過程中,ChatGPT 使用了解構語法,這會導致 isShow 失去其反應性。

解決方案

  1. 不使用解構語法:直接使用 props.isShow(或在 setup 函數中使用 props 參數)。
const props = defineProps();
// 使用 props.isShow
  1. 使用 toRefs 或 toRef:這些函數可以將 reactive 對象轉換為一組 ref 對象,這樣單獨的屬性仍然會保持其反應性。
import { toRefs } from 'vue';

const props = defineProps();
const { isShow } = toRefs(props);

原錯誤內容

透過這些調整,我們能確保 isShow 保持其反應性,從而使組件更為靈活和可維護。


上一篇
切版 動態樣式處理
下一篇
功能製作 (drag and drop mobile 上)
系列文
打造紐時風格的時間線小遊戲30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言